﻿
using System.Collections.Generic;

namespace XiaoweiV2
{
    /*
     * @comments: this file should keep consistent with xiaoweiAudioType.h
     */

    //public class SkillId
    //{
    //    public static readonly string Unknown = "8dab4796-fa37-4114-ffff-ffffffffffff";           /// skill name: 未知

    //    public static readonly string Music = "8dab4796-fa37-4114-0011-7637fa2b0001";             /// skill name: 音乐
    //    public static readonly string FM = "8dab4796-fa37-4114-0024-7637fa2b0001";                /// skill name: FM-*
    //    public static readonly string Weather = "8dab4796-fa37-4114-0012-7637fa2b0003";           /// skill name: 天气服务
    //    public static readonly string News = "8dab4796-fa37-4114-0019-7637fa2b0001";              /// skill name: 新闻
    //    public static readonly string Wiki = "8dab4796-fa37-4114-0020-7637fa2b0001";              /// skill name: 百科

    //    public static readonly string History = "8dab4796-fa37-4114-0027-7637fa2b0001";           /// skill name: 历史上的今天
    //    public static readonly string DateTime = "8dab4796-fa37-4114-0028-7637fa2b0001";          /// skill name: 当前时间
    //    public static readonly string Calc = "8dab4796-fa37-4114-0018-7637fa2b0001";              /// skill name: 计算器
    //    public static readonly string Translate = "8dab4796-fa37-4114-0030-7637fa2b0001";         /// skill name: 翻译
    //    public static readonly string Chat = "8dab4796-fa37-4114-0029-7637fa2b0001";              /// skill name: 闲聊

    //    public static readonly string IOTCtrl = "8dab4796-fa37-4114-0016-7637fa2b0001";           /// skill name: 物联-物联设备控制
    //    public static readonly string Alarm = "8dab4796-fa37-4114-0012-7637fa2b0001";             /// skill name: 提醒类
    //    public static readonly string Voip = "8dab4796-fa37-4114-0001-7637fa2b0002";              /// skill name: 视频通话
    //    public static readonly string VoipNoVideo = "8dab4796-fa37-4114-0002-7637fa2b0001";       /// skill name: 音频通话
    //    public static readonly string WechatMsg = "8dab4796-fa37-4114-0002-7637fa2b0002";         /// skill name: 通讯-微信消息

    //    public static readonly string Navigate = "8dab4796-fa37-4114-0015-7637fa2b0001";          /// skill name: 导航
    //    public static readonly string Video = "8dab4796-fa37-4114-0026-7637fa2b0001";             /// skill name: 视频
    //    public static readonly string TriggerAlarm = "8dab4796-fa37-4114-0036-7637fa2b0001";      /// skill name: 闹钟触发场景
    //    public static readonly string KTV = "8dab4796-fa37-4114-0040-7637fa2b0001";               /// skill name: K歌
    //    public static readonly string GeneralControl = "8dab4796-fa37-4114-0000-7637fa2b0000";    /// skill name: 通用控制

    //    public static readonly string IotMasterDevice = "8dab4796-fa37-4114-ffff-000000000000";   /// skill name:IOT主控
    //    public static readonly string IotControllerDevice = "8dab4796-fa37-4114-0037-7637fa2b0001";  /// skill name:设备被控
    //    public static readonly string Stock = "8dab4796-fa37-4114-0033-7637fa2b0001";             /// skill name:股票
    //    /** FM extend */
    //    public static readonly string FmHotProgram = "8dab4796-fa37-4114-0024-7637fa2b0002";      /// skill name:热门节目
    //    public static readonly string FmTraProgram = "8dab4796-fa37-4114-0024-7637fa2b0003";      /// skill name:传统电台

    //    public static readonly string FmNovel = "8dab4796-fa37-4114-0024-7637fa2b0004";           /// skill name:电子书
    //    public static readonly string FmStory = "8dab4796-fa37-4114-0024-7637fa2b0005";           /// skill name:故事
    //    public static readonly string FmJoke = "8dab4796-fa37-4114-0024-7637fa2b0006";            /// skill name:笑话
    //    public static readonly string FmNews = "8dab4796-fa37-4114-0024-7637fa2b0007";            /// skill name:新闻
    //    public static readonly string FmPingshu = "8dab4796-fa37-4114-0024-7637fa2b0008";         /// skill name:评书

    //    public static readonly string FmXiangsheng = "8dab4796-fa37-4114-0024-7637fa2b0009";      /// skill name:相声
    //    //extend skill by traning on skill center
    //    public static readonly string Lock = "8dab4796-fa37-1441-5b54-8f3f520ec016";              ///skill name: 锁屏
    //    public static readonly string Lock2 = "8dab4796-fa37-1441-5b72-3fdede8ec019";             ///skill name: 锁屏
    //    public static readonly string SettingPage = "8dab4796-fa37-1441-5bee-e91720c55001";       ///skill name: 设置页面
    //}
    public enum CommandId
    {
        /** volume and microphone */
        AddVolume        = 1000000, /// volume add {control_value}, -100 < controlValue < 100
        SetVolumeTo      = 1000001, /// volume set to {control_value}, 0 < controlValue < 100
        MuteSpeaker      = 1000002, /// speaker mute
        UnmuteSpeaker    = 1000003, /// speaker unmute
        MuteMic          = 1000004, /// microphone mute
        UnmuteMic        = 1000005, /// microphone unmute

        /** play control */
        Play             = 1000010, /// play/resume
        Stop             = 1000011, /// stop(the media can not resume, only can restart)
        Pause            = 1000012, /// pause
        Replay           = 1000013, /// restart current media
        Prev             = 1000014, /// play previous
        Next             = 1000015, /// play next
        PlayResource     = 1000016, /// play resource, {control_value} is the resource_id
        AddOffset        = 1000017, /// seek {control_value}, unit ms. positive value is forward and negative value means rewind
        SetOffsetTo      = 1000018, /// seek to {control_value}, unit ms.
        PlayMode         = 1000019, /// set play mode to {control_id}. 0: sequential 1: playlist loop 2: random 3: single loop

        /** device control */
        AddBrightness    = 1000050, /// brightness add {control_value}, -100 < controlValue < 100
        SetBrightnessTo  = 1000051, /// brightness set to {control_value}, 0 < controlValue < 100
        ReportState      = 1000100, /// report current state ASAP
        Shutdown         = 1000101, /// shutdown
        Reboot           = 1000102, /// reboot
        BluetoothModeOn  = 1000103, /// enter Bluetooth mode
        BluetoothModeOff = 1000104, /// exit Bluetooth mode
        DuplexModeOn     = 1000105, /// enter duplex mode
        DuplexModeOff    = 1000106, /// exit duplex mode
        UploadLog        = 1000107, /// need to upload log

        /** resource */
        Favorite         = 1100010, /// set {control_value}(resource_id) favorite
        Unfavorite       = 1100011, /// reset {control_value}(resource_id) favorite

        /** skill related */
        V2A              = 1200001, /// V2A matched, controlValue is json {"match_word":"xxx"}
    }

    public enum PlayMode
    {
        SequentialNoLoop   = 0,  /// sequential, finish playing while all resources are played
        SequentialLoopList = 1,  /// sequential loop
        ShuffleNoLoop      = 2,  /// shuffle playlist, finish playing while all resources are played
        ShuffleLoop        = 3,  /// shuffle playlist, loopy
        SingleLoop         = 4   /// single loop
    }

 /** @brief 设备当前的播放状态，用户应该在状态变化之后及时上报，只需要上报大资源，即打断后能够恢复的资源，例如音乐，FM。无需上报小资源，例如TTS播放。这里列举一下常用场景的上报：
 1. 切歌：报2次，首先第一首歌abort、然后第二首歌start(如果可以的话，先报preload，再start)。
 2. 播放过程中唤醒了开始语音请求(这时候正常音乐是要暂停的)：上报paused
 3. 操作2点了一首新歌，并且要准备播放了：先报刚才那首暂停的歌abort，再报新歌start
 4. 操作2问了一下天气或者闲聊：首先无需任何上报，音箱播放天气或者闲聊的TTS，对话结束之后正常逻辑应该恢复播放音乐，然后这时候上报resume。
 5. 该播放的东西播完了，无事可做：上报idle
 6. 一首歌自然播放完毕，开始播放下一首：上报第一首stop，再上报第二首start
 7. 所有的URL资源，如果可以的话，start之前先报preload
 8. 播放列表资源全部播放完毕，退出播放，上报finished，注意携带skilid。此时如果自动去播放别的了，就该报什么报什么，如果什么也不播放了，就上报idle。
    
 The current playing state of the device. The device should report ASAP while the state changes.
 Only resume-abled resources(resources that can be recovered after interruption) need to be reported, such as music and FM.
 No need to report nonrecoverable resources, such as TTS playback.
 Here are some common sample to report:
 1. switch song: report twice. Firstly, report the replaced song play_state_abort. Then report the new song play_state_start(It's better if you can report preload first).
 2. Interrupted by wakeup and voice request(the playing need to pause automaticly): report play_state_paused.
 3. If 2 asked for playing a new song:Report this paused song play_state_abort，then report new song play_state_start(It's better if you can report preload first).
 4. If 2 asked for the weather or chat：Firstly, no need for any report, just playing the weather or chat TTS, Then the privious song resume automaticly and report it play_state_resume.
 5. All resource play finish, nothing todo, report play_state_idle.
 6. A song play finish and play next song automaticly: Report the first one play_state_stoped, then report the next one play_state_start(It's better if you can report preload first).
 7. All URL resource, if possible, report preload befor start.
 8. Switch to a new skill and play list refreshed, report the previous play_state_abort and play_state_finished, Then report new one. Pay attention to report the correct skill ID.
 */
    public enum PlayState
    {
        Preload  = 0,        /// prepare or loading the resouce, in this state, play offset should be 0
        Start    = 1,        /// start playing, in this state, play offset should be 0
        Paused   = 2,        /// paused, can continue playing
        Stopped  = 3,        /// stoped, usually for the resource playing finish(automaticly), if manually, use play_state_abort
        Finished = 4,        /// all resource played, nothing to play
        Idle     = 5,        /// device idle, not at any skill
        Resume   = 6,        /// resume
        Abort    = 11,       /// abort, switch songs manually
        Error    = 12,       /// play error
    }

    public enum DeviceAvailability
    {
        /** Default, everything are available */
        Default              = 0x0000000000000000,

        /** Microphone is not available */
        MicNotAvailable      = 0x0000000000000001,

        /** Speaker is not available */
        SpeakerNotAvailable  = 0x0000000000000002,

        /** Do not disturb mode. In this mode, xiaowei will not initiate speak with users. */
        InitiativeSpeak      = 0x0000000000000004,

        /** Remote control(xiaowei APP and xiaowei mini APP) will be disabled. */
        DisableRemoteControl = 0x0000000000000008,
    }

    public enum ResourceFormat
    {
        Url      = 0,   /// URL resource, your player need to support MP3, AAC, m4a, FLAC and m3u8 type.
        Text     = 1,   /// Text resource, like a story. You can display it directly or translate it to TTS to play.
        TTS      = 2,   /// Deprecated, TTS reource's ID (real resource will be pushed by PCM packages with opus compress  (xiaowei_event_on_tts).
        File     = 3,   /// TTS URL, MP3 chuck, may need advanced player support.
        Location = 4,   /// Location resource
        Command  = 5,   /// Deprecated
        Intent   = 6,   /// Intent resource, special customization.
        TTS_URL  = 7,   /// Deprecated, Remind resource.
        Local    = 89,  /// Local resource (local official TTS package)
        Unknown  = 99   /// Unknow
    }

    public enum SkillType{
        Internal = 0,
        Local = 1,
        ThirdPart = 3
    }

    public struct Skill
    {
        public string Name;     /// skill name
        public string Id;       /// skill ID (define at the top of xiaoweiAudioType.h file)
        public SkillType Type;  /// skill type. 0:internal  1:local  2:3rd
    }

    public struct DeviceState
    {
        public Skill Skill;             /// current skill info, very important
        public PlayState PlayState;
        public DeviceAvailability Availability;
        public string PlayId;           /// current playing or pausing resourceID
        public string PlayContent;      /// current resource content
        public ulong PlayOffset;        /// current playing offset, unit ms
        public PlayMode PlayMode;       /// current play mode
        public ResourceFormat ResourceType; /// resource type

        /** if music, the flowing infos are recommended */
        public string ResouceName;      /// e.g. music name
        public string Performer;        /// e.g. singer
        public string Collection;       /// e.g abulm
        public string CoverUrl;

        public int Volume;              /// 0~100
        public int Brightness;          /// 0~100
    }


    /** @brief responseData type define */
    public enum ResponseType
    {
        Unknow            = 0,
        Card              = 1,    /// card
        Weather           = 2,    /// weather: json
        Game              = 3,    /// game
        Clock             = 4,    /// reminder: json
        English           = 5,    /// english reading/media: json
        LocalSkill        = 6,    /// local skill: intent and slot info
        Msgbox            = 7,    /// message box: json
        Fetch_device_info = 8,    /// fetch device info: json
        News              = 9,    /// news: json
        Wiki              = 10,   /// wiki: json
        MiniApp           = 11,   /// miniapp: json
        Voip              = 12,   /// voip
        IotDeviceList     = 13,   /// IOT device list
        IotOrgRequest     = 14,   /// IOT request text
        Tanslate          = 15,   /// translate: json
        // 16 to 30 are reserved
    }


    public enum WakeupProfile
    {
        Far = 0,    /// > 1m
        Near = 1,    /// < 1m
    }

    /** @brief  Wake-up type. In xiaowei_request(...), you must set this value in context.wakeup_type */
    public enum WakeupType
    {
        /** Local wake-up. There will be no more processing flow, cloud will processing audio data directly. */
        Local = 0,

        /** Cloud wake-up check. xiaowei_request(...).chat_type should be xiaowei_chat_via_wakeup_check.
         *  If your wake-up words is not end with "xiaowei", you need to set xiaowei_request(...).context.wakeup_words
         */
        Cloud = 1,

        /** Local wake-up with text. Some devices have difficulty splitting wake-up data and request voice data. This mode saved it.
         *  In this mode, you need to upload all voice data and set xiaowei_request(...).context.wakeup_words. So that the cloud will help you splitting them and remove the wake-up voice data in your request.
         */
        LocalWithText = 2,

        /** Local wake-up with free mode. In this mode, the cloud will keeping analysis the request untill you cancel this request. */
        LocalWithFree = 3,
    }

    /** @brief Wake-up flag. During the wake-up check process, you will recieve multiple responses (xiaowei_event_on_response). Decode the result and check the flag in XIAOWEI_PARAM_RESPONSE.wakeup_flag
 */
    public enum WakeupFlag
    {
        /** This response is not for a wake-up check request. */
        No              = 0,

        /** Wake-up failed */
        Fail            = 1,

        /** @deprecated use xiaowei_wakeup_flag_suc_continue and xiaowei_wakeup_flag_suc_rsp instead */
        /** Wake-up success, and no other words said by user (only said wake-up words). */
        Success         = 2,

        /** Wake-up success, and NLP analysis finish. You can get final response and resource in this time.
         *  The user said the wake-up words and continued to say the follow-up requirements without gap can trigger this derectly. Or, this is usually be triggered after multi xiaowei_wakeup_flag_suc_continue event.
         */
        SuccessRsp      = 3,

        /** Wake-up words is detected, and do not known if any other input (user is keep saying, silent event not triggered).
         *  This event may trigger multi-times, and after that, there are two possibilities: xiaowei_wakeup_flag_suc or xiaowei_wakeup_flag_suc_rsp
         */
        SuccessContinue = 4,
    }

    /** Context. Every xiaowei_request(...) need to take this. Also, you will get this in response (on_request_callback)
 *  Usually, a new context should be created before you calling xiaowei_request(...) for the first time in a round of request.
 */
    public class Context
    {
        /** Context ID.
         *  If you enter multiple round conversations, you will recieve a context by on_request_callback(event == xiaowei_event_on_response). Take out the ID in this context and set it into the next round's context.
         *  Otherwize, set this id null.
         */
        public string Id;

        /** Speak timeout, unit ms. If xiaowei_event_on_speak is not triggered within this time, an error will be generated and this round of request will be ended by SDK (xiaowei_event_on_idle will be triggered)
         *  Set this 5000 is recommended.
         *  In multiple round conversations, we suggest you set this by the last return's context.
         *  Only valid in voice request mode.
         */
        public uint SpeakTimeout;

        /** Silent timeout, unit micro seconds. Only valid when (this.request_param & xiaowei_param_local_vad != 0) and xiaowei_event_on_speak has been triggered. xiaowei_event_on_silent will be triggered if no new ASR result refresh within this time.
         *  Only valid in voice request mode.
         */
        public uint SilentTimeout;

        /** Must be true at, and only at the first calling of xiaowei_request(...) in a round of request.
         *  If this flag is true, a new round of request will be created by SDK.
         *  Set this true when the chat_type is not xiaowei_chat_via_voice
         */
        public bool VoiceRequestBegin;

        /** If you use local vad (xiaowei_param_local_vad), set this true at the last calling of xiaowei_request(...). No voice data length limitation at this time because it will be droped at all.
         *  Otherwize, set this false.
         */
        public bool VoiceRequestEnd;

        /** @See XIAOWEI_WAKEUP_PROFILE */
        public WakeupProfile WakeupProfile;

        /** @See XIAOWEI_WAKEUP_TYPE */
        public WakeupType WakeupType;

        /** @See XIAOWEI_WAKEUP_TYPE */
        public string WakeupWord;

        /** @See XIAOWEI_PARAM_PROPERTY */
        public ulong RequestParam;

        /** Local official TTS package version */
        public int LocalTtsVersion;

        /** If you take this in your request, only decleared skill will be hit by NLP */
        public Skill Skill;
    }

    public class Resource
    {
        public ResourceFormat Format;   /// resource format
        public string Id;               /// resource ID
        public string Content;          /// resource content. If format is URL, this is the URL, else if format is text, this is the text.
        public int PlayCount;           /// resource play count, usually TTS resource is 1. -1 means no limit.
        public ulong Offset;            /// play offset, unit ms.
        public string ExtendBuffer;     /// extend info, json type
    }
    public class ResourceGroup
    {
        public IList<Resource> Resources;
    }

    public enum PlaylistAction
    {
        ReplaceAll     = 0,    /// Replacing playlist. So that the current playing resource should be dropped.
        EnqueueFront   = 1,    /// Insert into the front of playlist, keep playing current resource.
        EnqueueBack    = 2,    /// Insert into the end of playlist, keep playing current resource.
        ReplaceEnqueue = 3,    /// Keep playing current resource, and replacing detail info in playlist, trigger UI refresh.
        RefreshURL     = 4,    /// Keep playing current resource, refreshing media URL in playlist.
        Remove         = 6,    /// Removing those resouces in playlist, if current playing resource is removed, switch to next resource immediately.
    }

    /** @brief Play list type. */
    public enum PlaylistType
    {
        Default = 0,        /// Default list (current list)/
        History = 1,        /// History list.
    }

    public struct ResponseParam
    {
        /** Skill hit in this request */
        public Skill Skill;

        /** Skill info before this request (current skill) */
        public Skill LastSkill;

        /** errocde, see deviceCommonDef.h */
        public int ErrorCode;

        /** voice id of the request */
        public string VoiceId;

        /** context for this request */
        public Context Context;

        /** ASR final result */
        public string RequestText;

        /** Json type for response_data @see {XIAOWEI_RESPONSE_TYPE} */
        public ResponseType ResponseType;

        /** Extra json data in some case */
        public string ResponseData;

        /** Extra intent data in some case */
        public string IntentInfo;

        /** size of resource_groups */
        //unsigned int resource_groups_size;

        /** reource group, get resources in this. Notice this is a pointer. Resources will be released when the callback function returns. Holding them by your self.
         */
        public IList<ResourceGroup> ResourceGroups;

        /** If true, means you can pull more resources by another request to add more resource at the end of playlist. */
        public bool HasMorePlaylist;

        /** If true, means this response has history play list to load */
        public bool HasHistoryPlaylist;

        /** If ture, means in this response, the resources can be resumed after pause or being interrupted. Otherwize you need to drop the resource once being interrupted. */
        public bool IsRecovery;

        /** If true, means in this resposne, the resources are notify information. Usually you can reduce the volume of the currently playing resources and play them. */
        public bool IsNotify;

        /** @see XIAOWEI_WAKEUP_FLAG */
        public WakeupFlag WakeupFlag;

        /** Play list action(operation) */
        public PlaylistAction PlayBehavior;

        /** Play list type, current list or history list */
        public PlaylistType ResourceListType;

        /** Answer text */
        public string ResponseText;

        /** Control ID, such as PAUSE, PLAY, NEXT..., @see XIAOWEI_DEVICE_CMD */
        public CommandId ControlId;

        /** Control value for the control ID */
        public string ControlValue;

        /** If true, means you can pull more resources by another request to add more resource at the front of playlist. */
        public bool HasMorePlaylistUp;
    }
    //================================================

    public enum Events///will be removed
    {
        Idle = 0,           // 空闲
        RequestStart = 1,   // 请求开始
        Speak = 2,          // 检测到说话
        Silent = 3,         // 检测到静音(only@device has not txca_device_local_vad)
        Recognize = 4,      // 识别文本实时返回
        Response = 5,       // 请求收到响应
        TTS = 6,            // 小微后台推送的TTS信息
        ResponseIntermediate = 7, //中间结果
        IotInfo = 8,        // iot info
    }


    public class ResponseData{
        public string VoiceId;
        public Events Evt;
        public ResponseParam Param;
        public string ExtendInfo;
        public int ExtendInfoLen;
    }


    public class Binder
    {
        public int Type;
        public string UserName;
        public string HeadUrl;
        public int Gender; 
    }

    public enum ResponseError
    {
        NotMatchSkill = 10010,
        MusicNotLogin = 10012,
        MusicNotFound = 10014,        // 某歌曲没有找到
        MusicNotHasLaw = 10015,     // 某歌曲没有版权
        MusicNotFoundResult = 10016, // 找不到音乐资源
        ErrMsgSendfailed = 131073,  //消息发送失败
        ErrMsgSendtimeout = 131074, //消息发送超时
        ErrAiAudioParseReq = 10000,          // 请求解包错误
        ErrAiAudioEmptyVoiceData = 10001,   // 空的语音数据
        ErrAiAudioVoiceToText = 10002,      // 语音转文本失败或结果为空
        ErrAiAudioTextAnalysis = 10003,      // 语义分析失败
        ErrAiAudioTextToVoice = 10004,      // 文本转语音失败  
        ErrConnectionTimeout = 33,
        ErrOfflineSDK = 20001,
        ErrVoicePackage = 10033,
    }
}
